package club.janna.netty.optimize;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 服务端 - 挑战单机百万连接
 */
public class Server {

    /**
     * 端口开始地址
     */
    private final static int DEFAULT_START_PORT = 9000;
    /**
     * 绑定多少个端口
     */
    private final static int DEFAULT_PORT_NUM = 100;

    public static void main(String[] args) {
        int startPort = DEFAULT_START_PORT;
        int portNum = DEFAULT_PORT_NUM;

        // 从命令行参数中读取配置
        if(args != null) {
            if(args.length >= 1) {
                if("help".equals(args[0])) {
                    System.out.println("java Server [startPort [portNum]]\r\n" +
                            "\tstartPort 开始的端口号（默认9000）\r\n" +
                            "\tportNum 要连接多少个端口（默认100）¡¡\r\n");
                    System.exit(0);
                }
                startPort = Integer.parseInt(args[0]);
            }
            if(args.length >= 2)
                portNum = Integer.parseInt(args[1]);
        }

        EventLoopGroup boosGroup = new NioEventLoopGroup(2);
        EventLoopGroup workGroup = new NioEventLoopGroup();

        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(boosGroup, workGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(CounterHandler.INSTANCE);
                    }
                });
        for (int i = 0; i < portNum; i++) {
            final int port = startPort + i;
            bootstrap.bind(port).addListener(future -> {
                if(future.isSuccess())
                    System.out.println("端口绑定成功，" + port);
                else
                    System.err.println("端口绑定失败，" + port);
            });
        }
        System.out.println("服务器启动成功");
        new Thread(() -> {
            while(true) {
                System.out.println("当前连接数 -> " + CounterHandler.count.get());
                try {
                    Thread.sleep(5000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    @ChannelHandler.Sharable
    private static class CounterHandler extends ChannelInboundHandlerAdapter {

        /**
         * 计数器，记录服务器当前有多少连接
         */
        public static final AtomicInteger count = new AtomicInteger(0);

        /**
         * 单例
         */
        public static final CounterHandler INSTANCE = new CounterHandler();

        private CounterHandler() {}

        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            count.incrementAndGet();
        }

        @Override
        public void channelInactive(ChannelHandlerContext ctx) throws Exception {
            count.decrementAndGet();
        }
    }
}
